package org.example.core.security;

import org.example.base.common.service.UserService;
import org.example.core.config.CommonConfiguration;
import org.example.core.security.filter.RequestLogFilter;
import org.example.core.security.filter.TokenLoginFilter;
import org.example.core.security.handler.LoginFailureHandler;
import org.example.core.security.handler.LoginSuccessHandler;
import org.example.core.security.service.LoginUserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private CommonConfiguration commonConfiguration;


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;


    @Autowired
    private LoginUserDetailServiceImpl loginUserDetailService;

    @Autowired
    private RequestLogFilter requestLogFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.logout().disable();//注销不需要跳转页面
        http.formLogin().disable();//登陆不成功不需要跳转页面
        http.cors().disable();
        http.csrf().disable();
        //处理可以访问的请求
        List<String> anonUrls = commonConfiguration.getSecurity().getAnonUrls();
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();
        if (!CollectionUtils.isEmpty(anonUrls)){
            for (String authUrl : anonUrls) {
                registry.antMatchers(authUrl).permitAll();
            }
        }
        List<String> authUrls = commonConfiguration.getSecurity().getAuthUrls();
        if (!CollectionUtils.isEmpty(authUrls)){
            for (String authUrl : authUrls) {
                registry.antMatchers(authUrl).authenticated();
            }
        }else {
            registry.antMatchers()
                    .authenticated();
        }

        http.addFilterBefore(tokenLoginFilter(), AnonymousAuthenticationFilter.class);
        http.addFilterBefore(requestLogFilter, DisableEncodeUrlFilter.class);
    }

    /**
     * 声明加密的Bean
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(loginUserDetailService).passwordEncoder(passwordEncoder());
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public TokenLoginFilter tokenLoginFilter() throws Exception {
        TokenLoginFilter filter = new TokenLoginFilter(redisTemplate, userService, loginFailureHandler, loginSuccessHandler);
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }
}


